/**
*@Created by YChienHung on 20-09-24.
*/

#include <iostream>
#include "opencv2/opencv.hpp"

#define WINDWOS_NAME "result1"

using namespace std;
using namespace cv;

void ShowMessage(Mat &img, int index);

Rect s_stMousePt;//老鼠的坐标

Point s_stHoleLeftUp;//洞的左上坐标
Point s_stHoleRightDown;//洞的右下坐标

/**
 * 显示处理结果
 * @param img
 * @param index from 1 to 9
 */
void ShowMessage(Mat &img, int index) {
    rectangle(img, Point(s_stMousePt.x, s_stMousePt.y),
              Point(s_stMousePt.x + s_stMousePt.width, s_stMousePt.y + s_stMousePt.height),
              Scalar(0, 0, 255), 2);
    putText(img, "Mouse in " + to_string(index), Point(0, 50),
            FONT_HERSHEY_DUPLEX, 2, Scalar(0, 0, 255), 2);
}

int main(int argc, char *args[]) {
    Mat img_blue, img_green, img_red;
    Mat frame;
    VideoCapture cap = VideoCapture("1.mp4");

    int8_t ucPos = 0;

    if (cap.isOpened()) {
        for (;;) {
            cap >> frame;
            if (frame.empty())
                break;
            //读通道
            vector<Mat> channels;
            split(frame, channels);  //分离色图像色彩通道，则三通道图像成为三个单通道图像

            //B G R
            img_blue = channels.at(0);
            img_green = channels.at(1);
            //img_red = channels.at(2);

            //二值化处理
            int threshold_max = 255;
            threshold(img_blue, img_blue, 210, threshold_max, THRESH_BINARY);//根据直方图来计算阈值
            threshold(img_green, img_green, 100, threshold_max, THRESH_BINARY);//根据直方图来计算阈值
            //threshold(img_red, img_red, 100, threshold_max, THRESH_BINARY);//根据直方图来计算阈值

            //处理杂点
            Mat kernel = getStructuringElement(MORPH_RECT, Size(40, 40));
            erode(img_blue, img_blue, kernel);  //腐蚀
            dilate(img_blue, img_blue, kernel); //膨胀

            Mat kernel2 = getStructuringElement(MORPH_RECT, Size(30, 35));

            dilate(img_green, img_green, kernel); //膨胀
            erode(img_green, img_green, kernel2);  //腐蚀

            //bitwise_not(img_green, img_green);//反色处理

            //寻找轮廓
            vector<vector<Point>> contours;
            vector<Vec4i> hierarchy;

            findContours(img_blue, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());

            //找老鼠
            if (contours.size() == 1) {
                //绘制轮廓的最小外结矩形
                RotatedRect rect = minAreaRect(contours[0]);
                Point2f P[4];
                rect.points(P);

                //记录一下老鼠的坐标信息
                s_stMousePt.x = P[3].x;
                s_stMousePt.y = P[3].y;
                s_stMousePt.width = P[1].x - P[3].x;
                s_stMousePt.height = P[1].y - P[3].y;
            }

            findContours(img_green, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());

            s_stHoleLeftUp.x = 9999;
            s_stHoleLeftUp.y = 9999;

            s_stHoleRightDown.x = 0;
            s_stHoleRightDown.y = 0;

            for (int i = 0; i < contours.size(); i++) {

                RotatedRect rect = minAreaRect(contours[i]);
                Point2f P[4];
                rect.points(P);

                //绝对值很重要
                int width = abs(P[1].x - P[3].x);
                int height = abs(P[1].y - P[3].y);

                if ((width) > 50 && width < 200 && (height) > 50 && height < 100) {

//                    绘制洞洞的矩形
//                    for (size_t j = 0; j < 4; j++)
//                        line(frame, P[j], P[(j + 1) % 4], Scalar(255, 255, 0), 2);

                    Point HoleCenter;
                    HoleCenter.x = P[1].x / 2 + P[3].x / 2;
                    HoleCenter.y = P[1].y / 2 + P[3].y / 2;

                    if (s_stHoleLeftUp.x > HoleCenter.x)
                        s_stHoleLeftUp.x = HoleCenter.x;

                    if (s_stHoleLeftUp.y > HoleCenter.y)
                        s_stHoleLeftUp.y = HoleCenter.y;

                    if (s_stHoleRightDown.x < HoleCenter.x)
                        s_stHoleRightDown.x = HoleCenter.x;

                    if (s_stHoleRightDown.y < HoleCenter.y)
                        s_stHoleRightDown.y = HoleCenter.y;
                }
            }

            int width = (s_stHoleRightDown.x - s_stHoleLeftUp.x) / 2;   //块宽度
            int height = (s_stHoleRightDown.y - s_stHoleLeftUp.y) / 2;  //块高度
            int x = round(fabs(s_stMousePt.x - s_stHoleLeftUp.x) / width) + 1;
            int y = round(fabs(s_stMousePt.y - s_stHoleLeftUp.y) / height);

            ucPos = x + y * 3;

            //绘制洞的范围
//            rectangle(frame, s_stHoleLeftUp, s_stHoleRightDown, Scalar(255, 0, 0), 2);

            ShowMessage(frame, ucPos);
            imshow(WINDWOS_NAME, frame);

            uint8_t key = waitKey(50);
            if (key == 'q' || key == 'Q')
                break;
        }
    }
    cap.release();// 释放视频句柄
    destroyAllWindows();//关闭所有窗口
    return 0;
}